﻿

namespace DynaPrecision.StandardFunction
{
	using System;
	using System.Collections.Generic;
	using System.Linq;
	using System.Text;
	/// <summary>
	/// Numerically Approximate The Error Function
	/// </summary>
	/// <typeparam name="TInput"></typeparam>
	/// <typeparam name="TOutput"></typeparam>
	public class ErrorFunction<TInput, TOutput> : FunctionAnalysis.IFunction<TInput, TOutput>
	{
		public ErrorFunction()
		{
			this.NumericalPrecisionOrder = 30;
		}
		protected void _decideProperOrder(TInput _x)
		{
			this.NumericalPrecisionOrder = (int)Math.Floor(Math.Abs((double)(dynamic)_x)/0.5)*15;
			if (this.NumericalPrecisionOrder < 30)
			{
				this.NumericalPrecisionOrder = 30;
			}
			if (this.NumericalPrecisionOrder > 1500)
			{
				this.NumericalPrecisionOrder = 1500;
			}
		}
		protected TOutput _evaluate(TInput _x)
		{
			return Numerical.SimpsonIntegrator.Integrate<TInput, TOutput>(
				DefaultValueProvider<TInput>.Zero, 
				(TInput)(dynamic)_x,
				__x => (dynamic)Math.Exp(__x * (dynamic)__x*-1), NumericalPrecisionOrder)/(dynamic)Math.Sqrt(Math.PI/4);
		}
		public int NumericalPrecisionOrder { get; set; }
		public Func<TInput, TOutput> Functor
		{
			get
			{
				return this._evaluate;
			}
		}

		public FunctionAnalysis.IFunction<TInput, TOutput> Derivative
		{
			get { throw new NotImplementedException(); }
		}

		public FunctionAnalysis.IFunction<TInput, TOutput> Integral
		{
			get { throw new NotImplementedException(); }
		}
	}
}
